import axios from 'axios'
import { useAuthStore } from '@/stores/auth'

let isRefreshing = false
let pendingQueue = []

function processQueue(error, token = null) {
  pendingQueue.forEach(({ resolve, reject }) => {
    if (error) {
      reject(error)
    } else {
      resolve(token)
    }
  })
  pendingQueue = []
}

export const http = axios.create({})

http.interceptors.request.use((config) => {
  const auth = useAuthStore()
  if (auth.accessToken) {
    config.headers = config.headers || {}
    config.headers['Authorization'] = 'Bearer ' + auth.accessToken
  }
  return config
})

http.interceptors.response.use(
  (resp) => resp,
  async (error) => {
    const auth = useAuthStore()
    const originalRequest = error.config || {}
    const url = (originalRequest.url || '').toString()

    // 不在认证端点上触发刷新；未持有访问令牌也不刷新
    const isAuthEndpoint = url.startsWith('/auth/')
    const hasToken = !!auth.accessToken
    if (!hasToken || isAuthEndpoint) {
      return Promise.reject(error)
    }

    if (error.response && error.response.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          pendingQueue.push({ resolve, reject })
        }).then((token) => {
          originalRequest.headers = originalRequest.headers || {}
          originalRequest.headers['Authorization'] = 'Bearer ' + token
          originalRequest._retry = true
          return http(originalRequest)
        })
      }

      originalRequest._retry = true
      isRefreshing = true
      try {
        const { data } = await axios.post('/auth/refresh')
        const newToken = data.accessToken
        auth.setAuth(newToken, auth.user)
        processQueue(null, newToken)
        originalRequest.headers = originalRequest.headers || {}
        originalRequest.headers['Authorization'] = 'Bearer ' + newToken
        return http(originalRequest)
      } catch (e) {
        processQueue(e, null)
        auth.clearAuth()
        return Promise.reject(e)
      } finally {
        isRefreshing = false
      }
    }
    return Promise.reject(error)
  }
)

export default http